home *** CD-ROM | disk | FTP | other *** search
/ Ham Radio 2000 #2 / Ham Radio 2000 - Volume 2.iso / HAMV2 / TCP_IP / TNOS230S / IPCMD.C < prev    next >
Encoding:
C/C++ Source or Header  |  1997-09-06  |  19.4 KB  |  790 lines

  1. /* IP-related user commands
  2.  * Copyright 1991 Phil Karn, KA9Q
  3.  */
  4. /* Mods by PA0GRI */
  5. #include "global.h"
  6. #include "commands.h"
  7. #include "mbuf.h"
  8. #include "internet.h"
  9. #include "timer.h"
  10. #include "netuser.h"
  11. #include "iface.h"
  12. #include "session.h"
  13. #include "rspf.h"
  14. #include "domain.h"
  15. #include "pool.h"
  16.  
  17. #if !defined(_lint)
  18. static char rcsid[] OPTIONAL = "$Id: ipcmd.c,v 1.21 1997/09/07 00:31:16 root Exp root $";
  19. #endif
  20.  
  21. uint32 Ip_addr;
  22. static int Route_Sort = 1;
  23. int Route_Same = 0;
  24.  
  25.  
  26. static int doadd (int argc, char *argv[], void *p);
  27.  
  28. #ifdef  IPACCESS
  29. static int doaccess (int argc, char *argv[], void *p);
  30. #endif
  31.  
  32. static int dodrop (int argc, char *argv[], void *p);
  33. static int doflush (int argc, char *argv[], void *p);
  34. static int doipaddr (int argc, char *argv[], void *p);
  35. static int doipstat (int argc, char *argv[], void *p);
  36. static int doiplook (int argc, char *argv[], void *p);
  37. static int dortimer (int argc, char *argv[], void *p);
  38. static int dottl (int argc, char *argv[], void *p);
  39. static int doiphport (int argc, char *argv[], void *p);
  40. static int doiphsize (int argc, char *argv[], void *p);
  41. void dumproute (struct route * rp, char *p);
  42. static int doroutesort (int argc, char *argv[], void *p);
  43. static int doroutesame (int argc, char *argv[], void *p);
  44.  
  45. /* IP heard logging - WG7J */
  46. static struct iph *iph_create (uint32 addr);
  47. static struct iph *iph_lookup (uint32 addr);
  48. static struct iph *Iph = NULLIPH;
  49.  
  50. static int Maxipheard = MAXIPHEARD;
  51.  
  52.  
  53. #ifdef CATALOG
  54. #include "catalog.h"
  55.  
  56. #define CAT ipcmd_catalog
  57.  
  58. #define accesshdr    __STR(0)
  59. #define accesssyntax    __STR(1)
  60. #define rtimerstr    __STR(2)
  61. #define ttlstr        __STR(3)
  62. #define iplookstr    __STR(4)
  63. #define reassembly    __STR(5)
  64. #define notfound    __STR(6)
  65. #define noaddroute    __STR(7)
  66. #define heardhdr    __STR(8)
  67. #define sortstr        __STR(9)
  68. #define iphsizestr    __STR(10)
  69. #define samestr        __STR(11)
  70.  
  71. #else /* CATALOG */
  72. static const char accesshdr[] = "Source Address  Len Dest Address    Len Interface    Proto   Low  High  State\n";
  73. static const char accesssyntax[] = " Format: ip access <permit|deny|delete> <proto> <src addr>[/<bits>] <dest addr>[/<bits>] <if name> [low [high]]\n";
  74. static const char rtimerstr[] = "IP reasm timeout (sec)";
  75. static const char ttlstr[] = "IP Time-to-live";
  76. static const char iplookstr[] = "Host %s (%s) unreachable\n";
  77. static const char reassembly[] = "Reassembly fragments:\n";
  78. static const char notfound[] = "Not found.\n";
  79. static const char noaddroute[] = "Can't add route\n";
  80. static const char heardhdr[] = "Tcp/Ip systems heard:\nAddress                Port       Since       Pkts\n";
  81. static const char sortstr[] = "Route Sort flag";
  82. static const char iphsizestr[] = "Max ip-heard";
  83. static const char samestr[] = "Permit IP routing out same interface it was received";
  84. #endif /* CATALOG */
  85.  
  86.  
  87. static const char allstr[] = "all";
  88. static const char anystr[] = "any";
  89. static const char icmpstr[] = "icmp";
  90. static const char tcpstr[] = "tcp";
  91. static const char udpstr[] = "udp";
  92. static const char denystr[] = "deny";
  93. static const char permitstr[] = "permit";
  94. static const char deletestr[] = "delete";
  95. static const char strCR[] = "%s\n";
  96. static const char defaultstr[] = "default";
  97. static const char rspfstr[] = "rspf   ";
  98. static const char manstr[] = "man    ";
  99. static const char directstr[] = "direct";
  100. static const char statdata[] = "(%2u)%-20s%10lu";
  101. static const char re_src[] = "src %s";
  102. static const char re_dest[] = " dest %s";
  103. static const char re_id[] = " id %u pctl %u time %lu len %u\n";
  104. static const char re_off[] = " offset %u last %u\n";
  105. static const char hearddata[] = "%-22s %-8s %12s %5ld\n";
  106. const char RouteHeader[] = "Destination      Len Interface Gateway          Metric P Timer  Use\n";
  107.  
  108.  
  109. #ifdef POOLED
  110. static struct mempool iph_pool = {NULLPOOLBLK, NULLPOOLBLK, 0, sizeof (struct iph), 50};
  111. #endif
  112.  
  113.  
  114.  
  115.  
  116. static struct cmds Ipcmds[] =
  117. {
  118. #ifdef  IPACCESS
  119.     { "access",    doaccess,    0, 0, NULLCHAR },
  120. #endif
  121.     { "address",    doipaddr,    0, 0, NULLCHAR },
  122.     { "heard",    doipheard,    0, 0, NULLCHAR },
  123.     { "hport",    doiphport,    0, 0, NULLCHAR },
  124.     { "hsize",    doiphsize,    0, 0, NULLCHAR },
  125.     { "routesame",    doroutesame,    0, 0, NULLCHAR },
  126.     { "rtimer",    dortimer,    0, 0, NULLCHAR },
  127.     { "status",    doipstat,    0, 0, NULLCHAR },
  128.     { "ttl",    dottl,        0, 0, NULLCHAR },
  129.     { NULLCHAR,    NULL,        0, 0, NULLCHAR }
  130. };
  131.  
  132.  
  133.  
  134. /* "route" subcommands */
  135. static struct cmds Rtcmds[] =
  136. {
  137.     { "add",    doadd,        0, 3, "route add <dest addr>[/<bits>] <if name> [<gateway> | direct [metric]]" },
  138.     { "addprivate",    doadd,        0, 3, "route addprivate <dest addr>[/<bits>] <if name> [<gateway> | direct [metric]]"},
  139.     { "drop",    dodrop,        0, 2, "route drop <dest addr>[/<bits>]" },
  140.     { "flush",    doflush,    0, 0, NULLCHAR },
  141.     { "lookup",    doiplook,    0, 2, "route lookup <dest addr>" },
  142.     { "sort",    doroutesort,    0, 0, NULLCHAR },
  143.     { NULLCHAR,    NULL,        0, 0, NULLCHAR }
  144. };
  145.  
  146.  
  147.  
  148. int
  149. doip (int argc, char *argv[], void *p)
  150. {
  151.     return subcmd (Ipcmds, argc, argv, p);
  152. }
  153.  
  154.  
  155.  
  156. #ifdef  IPACCESS
  157. static int
  158. doaccess (int argc, char *argv[], void *p OPTIONAL)
  159. {
  160. struct iface *ifp;
  161. uint32 source, target;
  162. unsigned sbits, tbits;
  163. char *bitp;
  164. int16 lport, hport, protocol, state;
  165. char const *cp;        /* for printing the table */
  166. struct rtaccess *tpacc;
  167. struct rtaccess *btacc;
  168. struct rtaccess *bfacc;
  169. struct rtaccess *head;
  170. char tmpbuf[15];
  171.  
  172.     if (argc == 1) {    /* print out the table */
  173.         tputs (accesshdr);
  174.         for (tpacc = IPaccess; tpacc != NULLACCESS; tpacc = tpacc->nxtiface) {
  175.             for (btacc = tpacc; btacc != NULLACCESS; btacc = btacc->nxtbits) {
  176.                 if (btacc->source != 0)
  177.                     cp = inet_ntoa (btacc->source);
  178.                 else
  179.                     cp = allstr;
  180.                 tprintf ("%-16s%2u  ", cp, btacc->sbits);
  181.                 if (btacc->target != 0)
  182.                     cp = inet_ntoa (btacc->target);
  183.                 else
  184.                     cp = allstr;
  185.                 tprintf ("%-16s%2u  %-13s", cp, btacc->bits, btacc->iface->name);
  186.                 switch (btacc->protocol) {
  187.                     case 0:        cp = anystr;
  188.                             break;
  189.                     case ICMP_PTCL:    cp = icmpstr;
  190.                             break;
  191.                     case TCP_PTCL:    cp = tcpstr;
  192.                             break;
  193.                     case UDP_PTCL:    cp = udpstr;
  194.                             break;
  195.                     default:    cp = itoa (btacc->protocol, tmpbuf, 10);
  196.                 }
  197.                 tprintf ("%-5s %5u %5u ", cp, btacc->lowport, btacc->highport);
  198.                 if (btacc->status)
  199.                     cp = denystr;
  200.                 else
  201.                     cp = permitstr;
  202.                 tprintf ("%-6s\n", cp);
  203.             }
  204.         }
  205.         return 0;
  206.     }
  207.     if (strcmp (argv[1], permitstr) == 0)
  208.         state = 0;
  209.     else {
  210.         if ((strcmp (argv[1], denystr) == 0) || (strcmp (argv[1], deletestr) == 0))
  211.             state = (int16) - 1;
  212.         else {
  213.             tputs (accesssyntax);
  214.             return 1;
  215.         }
  216.     }
  217.  
  218.     if (argc < 6) {
  219.         tputs (accesssyntax);
  220.         return 1;
  221.     }
  222.     switch (*argv[2]) {
  223.         case 'a':    /* ANY */
  224.             protocol = 0;
  225.             break;
  226.         case 'i':    /* ICMP */
  227.             protocol = ICMP_PTCL;
  228.             break;
  229.         case 't':    /* TCP */
  230.             protocol = TCP_PTCL;
  231.             break;
  232.         case 'u':    /* UDP */
  233.             protocol = UDP_PTCL;
  234.             break;
  235.         default:
  236.             protocol = (int16) atoi (argv[2]);
  237.     }
  238.  
  239.     if (strcmp (argv[3], allstr) == 0) {
  240.         source = 0;
  241.         sbits = 0;
  242.     } else {
  243.         /* If IP address is followed by an optional slash and
  244.          * a length field, (e.g., 128.96/16) get it;
  245.          * otherwise assume a full 32-bit address
  246.          */
  247.         if ((bitp = strchr (argv[3], '/')) != NULLCHAR) {
  248.             /* Terminate address token for resolve() call */
  249.             *bitp++ = '\0';
  250.             sbits = (unsigned int) atoi (bitp);
  251.         } else
  252.             sbits = 32;
  253.  
  254.         if ((source = resolve (argv[3])) == 0) {
  255.             tprintf (Badhost, argv[3]);
  256.             return 1;
  257.         }
  258.     }
  259.     if (strcmp (argv[4], allstr) == 0) {
  260.         target = 0;
  261.         tbits = 0;
  262.     } else {
  263.         if ((bitp = strchr (argv[4], '/')) != NULLCHAR) {
  264.             *bitp++ = '\0';
  265.             tbits = (unsigned int) atoi (bitp);
  266.         } else
  267.             tbits = 32;
  268.  
  269.         if ((target = resolve (argv[4])) == 0) {
  270.             tprintf (Badhost, argv[4]);
  271.             return 1;
  272.         }
  273.     }
  274.  
  275.     if ((ifp = if_lookup (argv[5])) == NULLIF) {
  276.         tprintf (Badinterface, argv[5]);
  277.         return 1;
  278.     }
  279.     if (((protocol != TCP_PTCL) && (protocol != UDP_PTCL)) || (argc < 7)) {
  280.         lport = 0;
  281.         hport = 0;
  282.     } else {
  283.         if (strcmp (argv[6], allstr) == 0)
  284.             lport = 0;
  285.         else
  286.             lport = (int16) atoi (argv[6]);
  287.  
  288.         if ((argc < 8) || (lport == 0))
  289.             hport = lport;
  290.         else
  291.             hport = (int16) atoi (argv[7]);
  292.     }
  293.  
  294.     if (strcmp (argv[1], deletestr) == 0) {
  295.         head = IPaccess;
  296.         for (tpacc = IPaccess; tpacc != NULLACCESS; head = tpacc, tpacc = tpacc->nxtiface) {
  297.             if (tpacc->iface == ifp) {
  298.                 for (btacc = tpacc; btacc != NULLACCESS; head = btacc, btacc = btacc->nxtbits) {
  299.                     if ((btacc->protocol == protocol) &&
  300.                         (btacc->source == source) &&
  301.                         (btacc->sbits == sbits) &&
  302.                         (btacc->target == target) &&
  303.                         (btacc->bits == tbits) &&
  304.                         (btacc->lowport == lport) &&
  305.                         (btacc->highport == hport)) {    /*match*/
  306.                         bfacc = btacc;    /* save to unalloc */
  307.                         /*now delete. watch for special cases*/
  308.                         if (btacc != tpacc) {    /* not at head of list */
  309.                             head->nxtbits = btacc->nxtbits;
  310.                             free (bfacc);
  311.                             return 0;
  312.                         }
  313.                         if (btacc == IPaccess) {    /* real special case */
  314.                             if (IPaccess->nxtbits == NULLACCESS)
  315.                                 IPaccess = btacc->nxtiface;
  316.                             else {
  317.                                 IPaccess = btacc->nxtbits;
  318.                                 (btacc->nxtbits)->nxtiface = btacc->nxtiface;
  319.                             }
  320.                         } else {    /* we know tpacc=btacc <> IPaccess */
  321.                             if (btacc->nxtbits == NULLACCESS)
  322.                                 head->nxtiface = btacc->nxtiface;
  323.                             else {
  324.                                 head->nxtiface = btacc->nxtbits;
  325.                                 (btacc->nxtbits)->nxtiface = btacc->nxtiface;
  326.                             }
  327.                         }
  328.                         free (bfacc);
  329.                         return 0;
  330.                     }
  331.                 }
  332.             }
  333.         }
  334.         tputs (notfound);
  335.         return 1;
  336.     }
  337.     /* add the access */
  338.     addaccess (protocol, source, sbits, target, tbits, ifp, lport, hport, state);
  339.     return 0;
  340. }
  341. #endif
  342.  
  343.  
  344.  
  345. static int
  346. doipaddr (int argc, char *argv[], void *p OPTIONAL)
  347. {
  348. uint32 n;
  349.  
  350.     if (argc < 2)
  351.         tprintf (strCR, inet_ntoa (Ip_addr));
  352.     else if ((n = resolve (argv[1])) == 0) {
  353.         tprintf (Badhost, argv[1]);
  354.         return 1;
  355.     } else
  356.         Ip_addr = n;
  357.     return 0;
  358. }
  359.  
  360.  
  361.  
  362. static int
  363. dortimer (int argc, char *argv[], void *p OPTIONAL)
  364. {
  365.     return setlong ((long *)&ipReasmTimeout, rtimerstr, argc, argv);
  366. }
  367.  
  368.  
  369.  
  370. static int
  371. dottl (int argc, char *argv[], void *p OPTIONAL)
  372. {
  373.     return setlong ((long *)&ipDefaultTTL, ttlstr, argc, argv);
  374. }
  375.  
  376.  
  377. /* Display and/or manipulate routing table */
  378. int
  379. doroute (int argc, char *argv[], void *p)
  380. {
  381. register int i, j, k, bits, flow_tmp;
  382. register struct route *rp;
  383. char *temp, temp2[80];
  384.  
  385.     if (argc >= 2)
  386.         return subcmd (Rtcmds, argc, argv, p);
  387.  
  388.     /* Dump IP routing table
  389.      * Dest            Len Interface    Gateway          Use
  390.      * 192.001.002.003 32  sl0          192.002.003.004  0
  391.      * modified for Sorted output - D. Crompton 2.92
  392.      */
  393.  
  394.     flow_tmp = Current->flowmode;
  395.     Current->flowmode = 1;
  396.  
  397.     tputs (RouteHeader);
  398.  
  399.     for (j = 0, bits = 31; bits >= 0; bits--)
  400.         for (i = 0; i < HASHMOD; i++)
  401.             for (rp = Routes[bits][i]; rp != NULLROUTE; j++, rp = rp->next)
  402.                 ;
  403.  
  404.     if (j) {
  405.  
  406.         temp = mallocw ((unsigned) j * 80);
  407.  
  408.         for (bits = 31, k = 0; bits >= 0; bits--)
  409.             for (i = 0; i < HASHMOD; i++)
  410.                 for (rp = Routes[bits][i]; rp != NULLROUTE; rp = rp->next, k += 80)
  411.                     dumproute (rp, &temp[k]);
  412.  
  413.         if (Route_Sort)
  414.             qsort (temp, (size_t) j, 80, (int (*)(const void *, const void *)) strcmp);
  415.  
  416.         for (i = 0, k = 4; i < j; i++, k += 80) {
  417.             tputs (&temp[k]);
  418.             if (tputc ('\n') == EOF) {
  419.                 Current->flowmode = flow_tmp;
  420.                 free (temp);
  421.                 return 0;
  422.             }
  423.         }
  424.         free (temp);
  425.     }
  426.     if (R_default.iface != NULLIF) {
  427.         dumproute (&R_default, temp2);
  428.         tprintf (strCR, &temp2[4]);
  429.     }
  430.     Current->flowmode = flow_tmp;
  431.     return 0;
  432. }
  433.  
  434.  
  435.  
  436. /* Dump a routing table entry */
  437. void
  438. dumproute (register struct route *rp, char *temp)
  439. {
  440. char const *cp;
  441. unsigned int a = 4;
  442. char *name;
  443.  
  444.     if (rp->target != 0) {
  445.         if (DTranslate && (name = resolve_a (rp->target, !DVerbose)) != NULLCHAR) {
  446.             strcpy (temp, name);
  447.             free (name);
  448.         } else {
  449.             cp = inet_ntobos (rp->target);
  450.             a = (unsigned int) SPRINTF ((temp, "%4s", cp));
  451.         }
  452.         cp = inet_ntoa (rp->target);
  453.     } else {
  454.         strcpy (temp, defaultstr);    /* Don't really matter, but avoid unknown value */
  455.         cp = "default";
  456.     }
  457.     a += (unsigned int) SPRINTF ((&temp[a], "%-16.16s ", cp));
  458.     a += (unsigned int) SPRINTF ((&temp[a], "%-4u", rp->bits));
  459.     a += (unsigned int) SPRINTF ((&temp[a], "%-9.9s ", rp->iface->name));
  460.     if (rp->gateway != 0)
  461.         cp = inet_ntoa (rp->gateway);
  462.     else
  463.         cp = "";
  464.     a += (unsigned int) SPRINTF ((&temp[a], "%-16.16s ", cp));
  465.     a += (unsigned int) SPRINTF ((&temp[a], "%-6lu ", rp->metric));
  466.     a += (unsigned int) SPRINTF ((&temp[a], "%c ", (rp->flags & RTPRIVATE) ? 'P' : ' '));
  467.     if (rp->timer.state == TIMER_STOP) {
  468.         if (rp->timer.duration == 1)
  469.             a += (unsigned int) SPRINTF ((&temp[a], rspfstr));
  470.         else
  471.             a += (unsigned int) SPRINTF ((&temp[a], manstr));
  472.     } else
  473.         a += (unsigned int) SPRINTF ((&temp[a], "%-7lu", read_timer (&rp->timer) / 1000L));
  474.     sprintf (&temp[a], "%lu", rp->uses);
  475. }
  476.  
  477.  
  478.  
  479. /* Sort Route dump */
  480. static int
  481. doroutesort (int argc, char *argv[], void *p OPTIONAL)
  482. {
  483.     return setbool (&Route_Sort, sortstr, argc, argv);
  484. }
  485.  
  486.  
  487. static int
  488. doroutesame (int argc, char *argv[], void *p OPTIONAL)
  489. {
  490.     return setbool (&Route_Same, samestr, argc, argv);
  491. }
  492.  
  493.  
  494. /* Add an entry to the routing table
  495.  * E.g., "add 1.2.3.4 ax0 5.6.7.8 3"
  496.  */
  497. static int
  498. doadd (int argc, char *argv[], void *p OPTIONAL)
  499. {
  500. struct iface *ifp;
  501. uint32 dest, gateway;
  502. unsigned bits;
  503. char *bitp;
  504. int32 metric;
  505. char private;
  506.  
  507.     if (strncmp (argv[0], "addp", 4) == 0)
  508.         private = 1;
  509.     else
  510.         private = 0;
  511.     if (strcmp (argv[1], defaultstr) == 0) {
  512.         dest = 0L;
  513.         bits = 0;
  514.     } else {
  515.         /* If IP address is followed by an optional slash and
  516.          * a length field, (e.g., 128.96/16) get it;
  517.          * otherwise assume a full 32-bit address
  518.          */
  519.         if ((bitp = strchr (argv[1], '/')) != NULLCHAR) {
  520.             /* Terminate address token for resolve() call */
  521.             *bitp++ = '\0';
  522.             bits = (unsigned int) atoi (bitp);
  523.         } else
  524.             bits = 32;
  525.  
  526.         if ((dest = resolve (argv[1])) == 0) {
  527.             tprintf (Badhost, argv[1]);
  528.             return 1;
  529.         }
  530.     }
  531.     if ((ifp = if_lookup (argv[2])) == NULLIF) {
  532.         tprintf (Badinterface, argv[2]);
  533.         return 1;
  534.     }
  535.     metric = 1;
  536.  
  537.     if (argc > 3) {
  538.         /* Next "trick is needed to set the metric on subnets
  539.          * higher as the default 1 for rspf.
  540.          * route add subnet/bits iface default 10
  541.          */
  542.         if (strcmp (argv[3], directstr) == 0) {    /* N1BEE */
  543.             gateway = 0;
  544.             /* calculate a nice metric based on subnet mask size */
  545.             if (bits != 0 && bits < 32)
  546.                 metric = (long) ((39 - bits) * 5 / 17);
  547.         } else {
  548.             if ((gateway = resolve (argv[3])) == 0) {
  549.                 tprintf (Badhost, argv[3]);
  550.                 return 1;
  551.             }
  552.         }
  553.     } else
  554.         gateway = 0;
  555.  
  556.     if (argc > 4)
  557.         metric = atol (argv[4]);
  558.  
  559.     if (rt_add (dest, bits, gateway, ifp, metric, 0, private) == NULLROUTE)
  560.         tputs (noaddroute);
  561. #ifdef  RSPF
  562.     if (!private)
  563.         rspfrouteupcall (dest, bits, gateway);    /* Do an RSPF upcall */
  564. #endif /* RSPF */
  565.     return 0;
  566. }
  567.  
  568.  
  569.  
  570. /* Drop an entry from the routing table
  571.  * E.g., "drop 128.96/16
  572.  */
  573. static int
  574. dodrop (int argc OPTIONAL, char *argv[], void *p OPTIONAL)
  575. {
  576. char *bitp;
  577. unsigned bits;
  578. uint32 n;
  579.  
  580.     if (strcmp (argv[1], defaultstr) == 0) {
  581.         n = 0L;
  582.         bits = 0;
  583.     } else {
  584.         /* If IP address is followed by an optional slash and length field,
  585.          * (e.g., 128.96/16) get it; otherwise assume a full 32-bit address
  586.          */
  587.         if ((bitp = strchr (argv[1], '/')) != NULLCHAR) {
  588.             /* Terminate address token for resolve() call */
  589.             *bitp++ = '\0';
  590.             bits = (unsigned int) atoi (bitp);
  591.         } else
  592.             bits = 32;
  593.  
  594.         if ((n = resolve (argv[1])) == 0) {
  595.             tprintf (Badhost, argv[1]);
  596.             return 1;
  597.         }
  598.     }
  599.     return rt_drop (n, bits);
  600. }
  601.  
  602.  
  603.  
  604. /* Force a timeout on all temporary routes */
  605. static int
  606. doflush (int argc OPTIONAL, char *argv[] OPTIONAL, void *p OPTIONAL)
  607. {
  608. register struct route *rp;
  609. struct route *rptmp;
  610. int i, j;
  611.  
  612.     if (R_default.timer.state == TIMER_RUN)
  613.         (void) rt_drop (0, 0);            /* Drop default route */
  614.  
  615.     for (i = 0; i < HASHMOD; i++) {
  616.         for (j = 0; j < 32; j++) {
  617.             for (rp = Routes[j][i]; rp != NULLROUTE; rp = rptmp) {
  618.                 rptmp = rp->next;
  619.                 if (rp->timer.state == TIMER_RUN)
  620.                     (void) rt_drop (rp->target, rp->bits);
  621.             }
  622.         }
  623.     }
  624.     return 0;
  625. }
  626.  
  627.  
  628.  
  629. static int
  630. doiplook (int argc OPTIONAL, char *argv[], void *p OPTIONAL)
  631. {
  632. struct route *rp;
  633. uint32 addr;
  634. char temp[80];
  635.  
  636.     addr = resolve (argv[1]);
  637.     if (addr == 0) {
  638.         tprintf (Badhost, argv[1]);
  639.         return 1;
  640.     }
  641.     if ((rp = rt_lookup (addr)) == NULLROUTE) {
  642.         tprintf (iplookstr, argv[1], inet_ntoa (addr));
  643.         return 1;
  644.     }
  645.     dumproute (rp, temp);
  646.     tputs (RouteHeader);
  647.     tprintf (strCR, &temp[4]);
  648.  
  649.     return 0;
  650. }
  651.  
  652.  
  653.  
  654. static int
  655. doipstat (int argc OPTIONAL, char *argv[] OPTIONAL, void *p OPTIONAL)
  656. {
  657. register struct reasm *rp;
  658. register struct frag *fp;
  659. int i;
  660.  
  661.     for (i = 1; i <= NUMIPMIB; i++) {
  662.         tprintf (statdata, i, Ip_mib[i].name, Ip_mib[i].value.integer);
  663.         if (i % 2)
  664.             tputs ("     ");
  665.         else
  666.             tputc ('\n');
  667.     }
  668.     if ((i % 2) == 0)
  669.         tputc ('\n');
  670.  
  671.     if (Reasmq != NULLREASM)
  672.         tputs (reassembly);
  673.     for (rp = Reasmq; rp != NULLREASM; rp = rp->next) {
  674.         tprintf (re_src, inet_ntoa (rp->source));
  675.         tprintf (re_dest, inet_ntoa (rp->dest));
  676.         if (tprintf (re_id, rp->id, uchar (rp->protocol), read_timer (&rp->timer), rp->length) == EOF)
  677.             break;
  678.         for (fp = rp->fraglist; fp != NULLFRAG; fp = fp->next) {
  679.             if (tprintf (re_off, fp->offset, fp->last) == EOF)
  680.                 break;
  681.         }
  682.     }
  683.     return 0;
  684. }
  685.  
  686.  
  687.  
  688. static int 
  689. doiphsize (int argc, char *argv[], void *p OPTIONAL)
  690. {
  691.     return setint (&Maxipheard, iphsizestr, argc, argv);
  692. }
  693.  
  694.  
  695.  
  696. /* Configure a port to do ip-heard logging */
  697. static int
  698. doiphport (int argc, char *argv[], void *p)
  699. {
  700.     return (dosetflag (argc, argv, p, LOG_IPHEARD, 0));
  701. }
  702.  
  703.  
  704.  
  705. int
  706. doipheard (int argc OPTIONAL, char *argv[] OPTIONAL, void *p OPTIONAL)
  707. {
  708. struct iph *iph;
  709.  
  710.     if (tputs (heardhdr) == EOF)
  711.         return EOF;
  712.     for (iph = Iph; iph; iph = iph->next) {
  713.         if (tprintf (hearddata, inet_ntoa (iph->addr), iph->iface->name, tformat (secclock () - iph->time), iph->count) == EOF)
  714.             return EOF;
  715.     }
  716.     return 0;
  717. }
  718.  
  719.  
  720.  
  721. void
  722. log_ipheard (uint32 addr, struct iface *ifp)
  723. {
  724. struct iph *niph;
  725.  
  726.     if ((niph = iph_lookup (addr)) == NULLIPH)
  727.         if ((niph = iph_create (addr)) == NULLIPH)
  728.             return;
  729.     niph->iface = ifp;
  730.     niph->count++;
  731.     niph->time = secclock ();
  732. }
  733.  
  734.  
  735.  
  736. /* Look up an entry in the ip data base */
  737. struct iph *
  738. iph_lookup (uint32 addr)
  739. {
  740. register struct iph *ip;
  741. struct iph *last = NULLIPH;
  742.  
  743.     for (ip = Iph; ip != NULLIPH; last = ip, ip = ip->next) {
  744.         if (ip->addr == addr) {
  745.             if (last != NULLIPH) {
  746.                 /* Move entry to top of list */
  747.                 last->next = ip->next;
  748.                 ip->next = Iph;
  749.                 Iph = ip;
  750.             }
  751.             return ip;
  752.         }
  753.     }
  754.     return NULLIPH;
  755. }
  756.  
  757.  
  758.  
  759. /* Create a new entry in the source database */
  760. /* If there are too many entries, override the oldest one - WG7J */
  761. static struct iph *
  762. iph_create (uint32 addr)
  763. {
  764. static int numdb = 0;
  765. register struct iph *iph;
  766. struct iph *last = NULLIPH;
  767.  
  768.     if (Maxipheard && numdb == Maxipheard) {
  769.         /* find and use last one in list */
  770.         for (iph = Iph; iph->next != NULLIPH; last = iph, iph = iph->next)
  771.             ;
  772.         /* delete entry from end */
  773.         if (last != NULLIPH)
  774.             last->next = NULLIPH;
  775.     } else {        /* create a new entry */
  776.         numdb++;
  777. #ifdef POOLED
  778.         iph = (struct iph *) pool_alloc (&iph_pool);
  779. #else
  780.         iph = (struct iph *) callocw (1, sizeof (struct iph));
  781.  
  782. #endif
  783.     }
  784.     iph->addr = addr;
  785.     iph->next = Iph;
  786.     Iph = iph;
  787.  
  788.     return iph;
  789. }
  790.